// 这里 Ctrl + 左键可以直接进入 Subscription 的 源码 TS的功能... JS应该也可以
import { Effect, ImmerReducer, Reducer, Subscription } from 'umi';// 用做interface接口的
// https://umijs.org/zh-CN/plugins/plugin-dva#model-%E7%94%A8%E4%BE%8B
// 找到 model 用例
// @umijs/plugin-dva
// 这里根据dva官网
// https://dvajs.com/api/#reducers

// 引入服务 也就是异步请求的 这里跟api是一个概念
import { getRemoteList, editRecord, delRecord, addRecord } from './service'


import {oneDataItemType} from './my.d'



// 导出这个接口 因为在index.tsx里面还要用到
export interface MyState { // ! 这里是state的接口
  data:oneDataItemType[], //使用了上面的接口
  mata:{
    total:number,
    per_page:number,
    page:number,
  }
}



// TS接口配置 配置完成后需要重启一下项目..
interface MyModelType {
  namespace: 'my',
  state: MyState,//套娃 上面
  reducers: {
    getList: Reducer<MyState> // ! 这里引出了一个泛型的概念 因为他的返回值其实就是state
  },
  effects: {
    function_name:Effect,
    getRemote:Effect,
    edit:Effect,
    add:Effect,
    del:Effect,
  },
  subscriptions: {
    setup: Subscription
  }
}

const MyModel: MyModelType = {
  namespace: "my", //唯一表示,命名空间 全局唯一
  state: {
    data:[],
    mata:{
      total:0,per_page:5,page:1 //声明默认值哦 因为上面写了接口
    }
  },
  reducers: {//返回页面数据必须用reducers
    // state 上一次的数据 必须return一个newState
    // action 里面有type 和payLoad 这里可以用{type,payLoad}来接收
    getList(state, action) { //这里的getList需要在上面的TS接口 声明他是一个Reducer
      // console.log('action: ', action);
      // return data
      return action.payload
    }
  },
  effects: {
    // 这里必须用*函数 这里是return void空值 无法返回数据
    *function_name(action, effects) { //这里是一个模板 没啥用的..
      // yield put()
    },
    // 获取远程数据
    *getRemote(action, effects) {
      // effects 里面有 put call 
      // put 是给 reducers;
      // call 是获取远程数据的
      const data = yield effects.call(getRemoteList) // 这里使用了异步请求的api 用call去调用 接受的参数会在data;es6 *函数的写法 英文叫 真呢略德
      // console.log('data: ', data); // 这里就是service 那边接口返回的data
      if (data) {

        yield effects.put({
          type: 'getList',//这里会跑去reducers
          payload: data // ! 这里需要传一个对象 所以套一层娃 重点 
          //  ! 现在因为后端是传过来一个response对象 所以直接这样就可以了 不可以是Array/其他
        })
      }
    },
    // ! 这是一个解构里面在解构的写法
    *edit({ payload: { id, values } }, { put, call }) {
      const data = yield call(editRecord, id, values)//传参必须这样传 不然会报错
      if (data) {
        yield put({
          type: 'getRemote'
        })
      }
    },

    *add({ payload: { values } }, { put, call }) {
      const data = yield call(addRecord, values)//传参必须这样传 不然会报错
      if (data) {
        yield put({
          type: 'getRemote'
        })
      }
    },

    *del({ payload: { id } }, { call, put }) {
      console.log('id: ', id);
      const data = yield call(delRecord, id)
      if (data) {
        yield put({
          type: "getRemote"
        })
      }
    }
  },
  subscriptions: {
    setup({ dispatch, history }, done) {
      // body..
      // location,action 这里 可以用 {pathname} 直接取出来 
      return history.listen((location, action) => { // return 官网给的demo有写return 但是不写也可以 可能是一种尾调用的性能优化写法
        //  B站老师说这个通过TS进去源码后有git地址 看history 复制他git的demo会报错 自己写就可以了
        if (location.pathname == '/my') {
          dispatch({ // ! dispatch 这里的type找的是自己模块的 所以不用 xx/xx
            // type:"getList" 走同步的方法 暂时不要了 
            type: "getRemote" // 走异步的方法 
          })
        }
      })
    }
  }
}

export default MyModel;//默认修改一下
